package com.service.impl;

import com.dao.ChatMessageDao;
import com.entity.ChatMessageEntity;
import com.service.MessageService;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;

import java.util.Arrays;
import java.util.Date;
import java.util.List;

import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.*;

/**
 * MessageServiceImpl单元测试
 */
@ExtendWith(MockitoExtension.class)
public class MessageServiceImplTest {

    @Mock
    private ChatMessageDao chatMessageDao;

    @InjectMocks
    private MessageServiceImpl messageService;

    private ChatMessageEntity testMessage;

    @BeforeEach
    void setUp() {
        testMessage = new ChatMessageEntity();
        testMessage.setId(1L);
        testMessage.setContent("Test message");
        testMessage.setSenderId("user1");
        testMessage.setReceiverId("user2");
        testMessage.setMessageType("text");
        testMessage.setIsRead(0);
        testMessage.setCreateTime(new Date());
    }

    @Test
    void testSaveMessage_Success() {
        // 模拟数据库插入成功
        when(chatMessageDao.insert(any(ChatMessageEntity.class))).thenReturn(1);

        // 执行测试
        boolean result = messageService.saveMessage("Test message", "user1", "user2");

        // 验证结果
        assertTrue(result);
        verify(chatMessageDao).insert(any(ChatMessageEntity.class));
    }

    @Test
    void testSaveMessage_Failure() {
        // 模拟数据库插入失败
        when(chatMessageDao.insert(any(ChatMessageEntity.class))).thenReturn(0);

        // 执行测试
        boolean result = messageService.saveMessage("Test message", "user1", "user2");

        // 验证结果
        assertFalse(result);
        verify(chatMessageDao).insert(any(ChatMessageEntity.class));
    }

    @Test
    void testSaveMessage_Exception() {
        // 模拟数据库异常
        when(chatMessageDao.insert(any(ChatMessageEntity.class)))
            .thenThrow(new RuntimeException("Database error"));

        // 执行测试
        boolean result = messageService.saveMessage("Test message", "user1", "user2");

        // 验证结果
        assertFalse(result);
        verify(chatMessageDao).insert(any(ChatMessageEntity.class));
    }

    @Test
    void testSaveMessage_WithNullContent() {
        // 测试空消息内容
        boolean result = messageService.saveMessage(null, "user1", "user2");

        // 验证结果
        assertFalse(result);
        verify(chatMessageDao, never()).insert(any(ChatMessageEntity.class));
    }

    @Test
    void testSaveMessage_WithEmptyContent() {
        // 测试空字符串消息内容
        boolean result = messageService.saveMessage("", "user1", "user2");

        // 验证结果
        assertFalse(result);
        verify(chatMessageDao, never()).insert(any(ChatMessageEntity.class));
    }

    @Test
    void testSaveMessage_WithNullSenderId() {
        // 测试空发送者ID
        boolean result = messageService.saveMessage("Test message", null, "user2");

        // 验证结果
        assertFalse(result);
        verify(chatMessageDao, never()).insert(any(ChatMessageEntity.class));
    }

    @Test
    void testSaveMessage_WithNullReceiverId() {
        // 测试空接收者ID
        boolean result = messageService.saveMessage("Test message", "user1", null);

        // 验证结果
        assertFalse(result);
        verify(chatMessageDao, never()).insert(any(ChatMessageEntity.class));
    }

    @Test
    void testSaveMessage_MessageEntityFields() {
        // 模拟数据库插入成功
        when(chatMessageDao.insert(any(ChatMessageEntity.class))).thenReturn(1);

        // 执行测试
        messageService.saveMessage("Test message", "user1", "user2");

        // 验证插入的消息实体字段
        verify(chatMessageDao).insert(argThat(entity -> {
            return "Test message".equals(entity.getContent()) &&
                   "user1".equals(entity.getSenderId()) &&
                   "user2".equals(entity.getReceiverId()) &&
                   "text".equals(entity.getMessageType()) &&
                   entity.getIsRead() == 0 &&
                   entity.getCreateTime() != null;
        }));
    }

    @Test
    void testSaveMessage_WithSpecialCharacters() {
        // 测试包含特殊字符的消息
        String specialMessage = "消息包含特殊字符：@#$%^&*()_+{}|:<>?[]\\;'\",./";
        when(chatMessageDao.insert(any(ChatMessageEntity.class))).thenReturn(1);

        boolean result = messageService.saveMessage(specialMessage, "user1", "user2");

        assertTrue(result);
        verify(chatMessageDao).insert(argThat(entity -> 
            specialMessage.equals(entity.getContent())
        ));
    }

    @Test
    void testSaveMessage_WithLongMessage() {
        // 测试长消息
        StringBuilder longMessage = new StringBuilder();
        for (int i = 0; i < 1000; i++) {
            longMessage.append("这是一条很长的消息内容。");
        }
        
        when(chatMessageDao.insert(any(ChatMessageEntity.class))).thenReturn(1);

        boolean result = messageService.saveMessage(longMessage.toString(), "user1", "user2");

        assertTrue(result);
        verify(chatMessageDao).insert(argThat(entity -> 
            longMessage.toString().equals(entity.getContent())
        ));
    }

    @Test
    void testSaveMessage_WithUnicodeCharacters() {
        // 测试Unicode字符
        String unicodeMessage = "Unicode消息：你好世界！🌍🚀💻";
        when(chatMessageDao.insert(any(ChatMessageEntity.class))).thenReturn(1);

        boolean result = messageService.saveMessage(unicodeMessage, "user1", "user2");

        assertTrue(result);
        verify(chatMessageDao).insert(argThat(entity -> 
            unicodeMessage.equals(entity.getContent())
        ));
    }

    @Test
    void testSaveMessage_WithWhitespaceContent() {
        // 测试只包含空白字符的消息
        boolean result = messageService.saveMessage("   \t\n   ", "user1", "user2");

        assertFalse(result);
        verify(chatMessageDao, never()).insert(any(ChatMessageEntity.class));
    }

    @Test
    void testSaveMessage_WithEmptyUserId() {
        // 测试空用户ID
        boolean result = messageService.saveMessage("Test message", "", "user2");

        assertFalse(result);
        verify(chatMessageDao, never()).insert(any(ChatMessageEntity.class));
    }

    @Test
    void testSaveMessage_WithEmptyReceiverId() {
        // 测试空接收者ID
        boolean result = messageService.saveMessage("Test message", "user1", "");

        assertFalse(result);
        verify(chatMessageDao, never()).insert(any(ChatMessageEntity.class));
    }

    @Test
    void testSaveMessage_WithVeryLongUserId() {
        // 测试超长用户ID
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < 100; i++) {
            sb.append("a");
        }
        String longUserId = sb.toString();
        when(chatMessageDao.insert(any(ChatMessageEntity.class))).thenReturn(1);

        boolean result = messageService.saveMessage("Test message", longUserId, "user2");

        assertTrue(result);
        verify(chatMessageDao).insert(argThat(entity -> 
            longUserId.equals(entity.getSenderId())
        ));
    }

    @Test
    void testSaveMessage_WithVeryLongReceiverId() {
        // 测试超长接收者ID
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < 100; i++) {
            sb.append("b");
        }
        String longReceiverId = sb.toString();
        when(chatMessageDao.insert(any(ChatMessageEntity.class))).thenReturn(1);

        boolean result = messageService.saveMessage("Test message", "user1", longReceiverId);

        assertTrue(result);
        verify(chatMessageDao).insert(argThat(entity -> 
            longReceiverId.equals(entity.getReceiverId())
        ));
    }

    @Test
    void testSaveMessage_ConcurrentAccess() throws InterruptedException {
        // 测试并发访问
        when(chatMessageDao.insert(any(ChatMessageEntity.class))).thenReturn(1);

        int threadCount = 10;
        Thread[] threads = new Thread[threadCount];
        boolean[] results = new boolean[threadCount];

        // 创建多个线程同时保存消息
        for (int i = 0; i < threadCount; i++) {
            final int index = i;
            threads[i] = new Thread(() -> {
                results[index] = messageService.saveMessage(
                    "Message " + index, 
                    "user" + index, 
                    "receiver" + index
                );
            });
        }

        // 启动所有线程
        for (Thread thread : threads) {
            thread.start();
        }

        // 等待所有线程完成
        for (Thread thread : threads) {
            thread.join();
        }

        // 验证所有操作都成功
        for (boolean result : results) {
            assertTrue(result);
        }

        // 验证数据库被调用了正确的次数
        verify(chatMessageDao, times(threadCount)).insert(any(ChatMessageEntity.class));
    }
}
